#define _CRT_SECURE_NO_WARNINGS 1

//字符串左旋
//实现一个函数，可以左旋字符串中的k个字符。
//例如：
//ABCD左旋一个字符得到BCDA
//ABCD左旋两个字符得到CDAB

//法一
//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//void string_left_rotate(char* str, int n)
//{
//	assert(str != NULL);
//	int sum = strlen(str);
//	for (int i = 0;i < n;i++)//旋转几个字符就循环几次
//	{
//		char tmp = *str;//1.把第一个字符存起来
//		for (int j = 0;j < sum - 1;j++)
//		{
//			*(str + j) = *(str + j + 1);//2.把第一个后面的字符依次往前挪动一位
//		}
//		*(str + sum - 1) = tmp;//3.把第一个字符放到最后
//	}
//}
//int main()
//{
//	char arr[20] = "abcdef";
//	printf("%s\n", arr);
//	int n = 0;
//	scanf("%d", &n);
//	string_left_rotate(arr, n);
//	printf("%s\n", arr);
//	return 0;
//}

//法二 三步翻转法
//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//void reverse(char* left, char* right)
//{
//	assert(left != NULL);
//	assert(right != NULL);
//	while (left < right)
//	{
//		char tmp = *left;
//		*left = *right;
//		*right = tmp;
//		left++;
//		right--;
//	}
//}
//void string_left_rotate(char* str, int n)
//{
//	int sum = strlen(str);
//	assert(str!=NULL);
//	//如ABCDEF  n=2
//	reverse(str, str+n-1);//1.翻转要左旋的n个字符  BA CDEF
//	reverse(str+n, str + sum - 1);//2.翻转要剩余的个字符 BA FEDC
//	reverse(str, str + sum - 1);//3.整体旋转  CDEF AB
//}
//int main()
//{
//	char arr[20] = "ABCEDF";
//	printf("%s\n", arr);
//	int n = 0;
//	scanf("%d", &n);
//	string_left_rotate(arr, n);
//	printf("%s\n", arr);
//	return 0;
//}

//字符串旋转
//写一个函数，判断一个字符串是否为另外一个字符串旋转之后的字符串。
//例如：给定s1 = AABCD和s2 = BCDAA，返回1
//给定s1 = abcd和s2 = ACBD，返回0.
//AABCD左旋一个字符得到ABCDA
//AABCD左旋两个字符得到BCDAA
//AABCD右旋一个字符得到DAABC

////法一（暴力穷举法）：
//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//int is_string_rotate(char* str1, char* str2)
//{
//    //穷举str1所有左旋的结果，然后和str2比较（右旋是左旋的特殊形式）
//    assert(str1 != NULL);
//    assert(str2 != NULL);
//    int sum = strlen(str1);
//    for (int i = 0;i < sum;i++)//旋转str1所有的结果
//    {
//        char tmp = *str1;//1.把第一个字符存起来
//        for (int j = 0;j < sum - 1;j++)
//        {
//            *(str1 + j) = *(str1 + j + 1);//2.把第一个后面的字符依次往前挪动一位
//        }
//        *(str1 + sum - 1) = tmp;//3.把第一个字符放到最后
//
//        //旋转一个字符比较一次
//        if (strcmp(str1, str2) == 0)
//        {
//            return 1;
//        }
//    }
//    return 0;//所有结果比较完，没有就返回0
//}
//int main()
//{
//    char arr1[20] = "ABCDEF";
//    char arr2[20] = "CDEFAB";
//    if (is_string_rotate(arr1, arr2))//是就返回1
//    {
//        printf("yes\n");
//    }
//    else
//    {
//        printf("no\n");
//    }
//    return 0;
//}

////法二：
//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//int is_string_rotate(char* str1, char* str2)
//{
//    assert(str1 != NULL);
//    assert(str2 != NULL);
//    if (strlen(str1) != strlen(str2))
//    {
//        return 0;   //长度不相等返回0
//    }
//    int sum = strlen(str1);
//    //1.给str1追加一个str1
//    //如ABCDEF变成ABCDEFABCDEF  这样新字符串的其中6个就包含了原字符串旋转的所有可能
//    strncat(str1, str1, sum);//字符串追加函数，在第一个参数后面追加第三个参数个第二个参数的字符串
//    //（strcat不能给自己追加，strncat多最后一个参数）
//    
//    //2.比较str2是不是str1新字符串的子字符串（是的话就是str1原字符串旋转得来）
//    char* ret = strstr(str1, str2);//判断第二个参数是否是第一个参数的子字符串
//    //是的话返回第一个参数中子字符串的首地址，不是的话返回空指针
//    //注意到如果长度不一样也是子字符串，不合题意，所以一开始判断长度
//    return ret != NULL; //是空指针返回0，不是返回1
//}
//int main()
//{
//    char arr1[20] = "ABCDEF";
//    char arr2[20] = "CDEFAB";
//    if (is_string_rotate(arr1, arr2))//是就返回1
//    {
//        printf("yes\n");
//    }
//    else
//    {
//        printf("no\n");
//    }
//    return 0;
//}

////strlen
//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	const char* str1 = "abcd";
//	const char* str2 = "abcdef";
//	if (strlen(str1) - strlen(str2) > 0)
//	{
//		printf("str1>str2\n");
//	}
//	else
//	{
//		printf("srt1<=str2\n");
//	}
//	return 0;
//}
////输出str1>str2 因为无符号减无符号还是无符号

//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//int my_strlen1(const char* str)//计数器版本
//{
//    assert(str != NULL);
//    int count = 0;
//    while (*str != '\0')
//    {
//        count++;
//        str++;
//    }
//    return count;
//}
//int my_strlen2(const char* str)//递归版本
//{
//    assert(str != NULL);
//    if (*str != '\0')
//        return 1 + my_strlen2(str + 1);
//    else
//        return 0;
//}
////左下右上转圈地看
////my(hello)
////my(hello)     1+my(ello) =5
////my(ello)      1+my(llo)  =4
////my(llo)       1+my(lo)   =3
////my(lo)        1+my(o)    =2
////my(o)  return 1+my(\0)   =1
////my(\0):return 0;
//int my_strlen3(const char* str)//指针减指针版本
//{
//    assert(str != NULL);
//    char* ret = str;
//    while (*ret != '\0')
//    {
//        ret++;
//    }
//    return ret - str;
//}
//int main()
//{
//    char arr[] = "hello";
//    printf("%d\n", strlen(arr));
//    printf("%d\n", my_strlen1(arr));
//    printf("%d\n", my_strlen2(arr));
//    printf("%d\n", my_strlen3(arr));
//    return 0;
//}

//char* strcpy(char* destination, const char* source);
//
//Copies the C string pointed by source into the array pointed by destination, including the
//terminating null character(and stopping at that point).
//源字符串必须以 '\0' 结束。
//会将源字符串中的 '\0' 拷贝到目标空间。
//目标空间必须足够大，以确保能存放源字符串。
//目标空间必须可变。
//strcpy函数的模拟实现:

//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//char* my_strcpy(char* dest, const char* src)
//{
//	assert(dest != NULL);
//	assert(src != NULL);
//	char* ret = dest;//让ret指向dest的起始地址
//	while (*dest++ = *src++)//'\0'的ASCII码为0拷贝后跳出循环
//	{
//		;
//	}
//	return ret;
//}
//int main()
//{
//	char arr1[50] = "#####################";
//	char arr2[] = "hello world";
//	//printf("%s\n", strcpy(arr1, arr2));
//	printf("%s\n", my_strcpy(arr1, arr2));
//	return 0;
//}

//strcatchar* strcat(char* destination, const char* source);

//Appends a copy of the source string to the destination string.
// The terminating null character in destination is overwritten 
// by the first character of source, and a null - character is 
// included at the end of the new string formed by the concatenation 
// of both in destination.
//源字符串必须以 '\0' 结束。
//目标空间必须有足够的大，能容纳下源字符串的内容。
//目标空间必须可修改。
//字符串自己给自己追加，要用到strncat

//strcat函数模拟实现 :
//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//char* my_strcat(char* dest, const char* src)
//{
//	assert(dest != NULL);
//	assert(src != NULL);
//	char* ret = dest;//让ret指向dest的起始地址
//	while (*dest)//找到'\0'  '\0'的ASCII码为0跳出循环
//	{
//		dest++;
//	}
//	while (*dest++ = *src++)//'\0'的ASCII码为0拷贝后跳出循环
//	{
//		;
//	}
//	return ret;
//}
//int main()
//{
//	char arr1[20] = "hello ";
//	char arr2[] = "world";
//    //printf("%s\n", strcat(arr1, arr2));
//	printf("%s\n", my_strcat(arr1, arr2));
//	return 0;
//}

//int strcmp(const char* str1, const char* str2);

//This function starts comparing the first character of each string.
//If they are equal to each other, it continues with the following pairs 
//until the characters differ or until a terminating
//null - character is reached.
//标准规定：
//第一个字符串大于第二个字符串，则返回大于0的数字
//第一个字符串等于第二个字符串，则返回0
//第一个字符串小于第二个字符串，则返回小于0的数字

////strcmp函数模拟：
//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//int my_strcmp(const char* str1, const char* str2)
//{
//	assert(str1 != NULL);
//	assert(str2 != NULL);
//	while (*str1 == *str2)
//	{
//		if (*str1)//如果两个相等且其中一个为\0
//		{
//			return 0;
//		}
//		else
//		{
//			str1++;
//			str2++;
//		}
//	}
//	return *str1 - *str2;//返回>0或<0才是标准，而且可以看相差的ASCII码
//}
//int main()
//{
//	char arr1[] = "abcd";
//	char arr2[] = "abcd";
//	/*if (strcmp(arr1, arr2) > 0)
//	{
//		printf("arr1>arr2\n");
//	}
//	else if (strcmp(arr1, arr2) < 0)
//	{
//		printf("arr1<arr2\n");
//	}
//	else
//	{
//		printf("arr1=arr2\n");
//	}*/
//	if (my_strcmp(arr1, arr2) > 0)
//	{
//		printf("arr1>arr2\n");
//	}
//	else if (my_strcmp(arr1, arr2) < 0)
//	{
//		printf("arr1<arr2\n");
//	}
//	else
//	{
//		printf("arr1=arr2\n");
//	}
//	return 0;
//}

//char* strstr(const char* str1, const char* str2);
//
//在str1字符串中查找是否包含str2字符串，
//如果存在则返回的是第一次出现位置的字符串，
//如果不存在，则返回的是null，如果str2传的为空串则返回str1
//strstr模拟实现：

//#include<stdio.h>
//#include<string.h>
//#include<assert.h>
//char* my_strstr(const char* str1, const char* str2)
//{
//	assert(str1 != NULL);
//	if (str2 == NULL)
//	{
//		return (char*)str1; //库函数里面的实现
//	}     //强制类型转化为要返回的类型，本来类型是const char*
//	const char* s1 = str1;
//	const char* s2 = str2;
//	const char* p = str1;
//	while (*p)
//	{
//		s1 = p;        //一次匹配不成功p++后继续匹配
//		s2 = str2;
//		while (*s1 && *s2 && (*s1 == *s2))//其中一个为\0或者不相等就跳出
//		{
//			s1++;   //可以把两个++放到上面( )
//			s2++;
//		}
//		if (*s2 == '\0') //匹配成功
//		{
//			return (char*)p;//强制类型转化为要返回的类型，本来类型是const char*
//		}
//		p++;         //一次匹配不成功p++后继续匹配
//	}
//	return NULL;
//}
//int main()
//{
//	char arr1[] = "abcdef";
//	char arr2[] = "cd";
//	/*if (strstr(arr1, arr2) == NULL)
//	{
//		printf("找不到");
//	}
//	else
//	{
//		printf("找到了：%s\n", strstr(arr1, arr2));
//	}*/
//	if (my_strstr(arr1, arr2) == NULL)
//	{
//		printf("找不到");
//	}
//	else
//	{
//		printf("找到了：%s\n", my_strstr(arr1, NULL));
//	}
//	return 0;
//}

//2.9 strtok
//char* strtok(char* str, const char* sep);
//
//sep参数是个字符串，定义了用作分隔符的字符集合
//第一个参数指定一个字符串，它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
//strtok函数找到str中的下一个标记，并将其用 \0 结尾，返回一个指向这个标记的指针。
//（注：strtok函数会改变被操作的字符串，所以在使用strtok函数切分的字符串一般都是用strcpy
//临时拷贝的内容并且可修改。）
//strtok函数的第一个参数不为 NULL ，函数将找到str中第一个标记，
//strtok函数将保存它在字符串中的位置。
//strtok函数的第一个参数为 NULL ，函数将在同一个字符串中被保存的位置开始，查找下一个标记。
//如果字符串中不存在更多的标记，则返回 NULL 指针。
//
//分割邮箱使用演示：
//#include<stdio.h>
//#include<string.h>
//int main()
//{
//    char email[] = "zpw@bitejiuyeke.com.net";
//    char* sep = "@.";
//    char tmp[40] = { 0 };
//    strcpy(tmp, email);
//    for(char* ret = strtok(tmp, sep); ret != NULL;ret = strtok(NULL, sep))
//    {
//        printf("%s\n", ret);
//    }
//    return 0;
//}

//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	printf("%s\n", strerror(0));
//	printf("%s\n", strerror(1));
//	printf("%s\n", strerror(2));
//	printf("%s\n", strerror(3));
//	printf("%s\n", strerror(4));
//	printf("%s\n", strerror(5));
//	return 0;
//}
//#include<stdio.h>
//#include<string.h>
//#include<errno.h>
//int main()
//{
//	FILE* pf = fopen("test.txt", "r");//打开文件操作，后面会学
//	if (pf == NULL)
//	{
//		printf("%s\n", strerror(errno));
//		return 1;
//	}
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

#include<stdio.h>
#include<string.h>
int main()
{
    unsigned char puc[4];
    struct tagPIM
    {
        unsigned char ucPim1;
        unsigned char ucData0 : 1;
        unsigned char ucData1 : 2;
        unsigned char ucData2 : 3;
    }*pstPimData;
    pstPimData = (struct tagPIM*)puc;
    memset(puc, 0, 4);
    pstPimData->ucPim1 = 2;
    pstPimData->ucData0 = 3;
    pstPimData->ucData1 = 4;
    pstPimData->ucData2 = 5;
    printf("%02x %02x %02x %02x\n", puc[0], puc[1], puc[2], puc[3]);
    return 0;
}